package SPA;


/**
 * Deterministic Finite Automaton
 */
public class DFA 
{
	private String name;			// name of the automaton
	private DFAState [] states; 	// list of states of the automaton
	
	/**
	 * Constructor
	 * @param name			name of the Automaton
	 * @param initialState	initial state of the automaton (always the first one to be added)
	 */
	public DFA (String name, DFAState initialState)
	{
		this.name = name;
		
		this.states = new DFAState [1];		
		this.addState(initialState);
	}
	
	/**
	 * Adds a new state to the automaton
	 * @param state
	 */
	public void addState (DFAState state)
	{
		if (this.verifyState(state))
		{
			states[states.length-1] = state;
			DFAState [] temp = new DFAState [states.length +1];
			System.arraycopy(states, 0, temp, 0, states.length);
			states = temp;
		}
		else
			System.out.println("  >> ERROR! State(" + state.getId() + ") already exists!");
	}
	
	/**
	 * Gets an existent state of the automaton
	 * @param id	ID (name) of the desired state
	 * @return		return the desired State. NULL if the state does not exist
	 */
	public DFAState getState(int id)
	{
		for (int i = 0; i < states.length - 1; i++)
		{
			if (states[i].getId() == id)
				return states[i];
		}
		
		return null;
	}
	
	/**
	 * Gets the Initial State of the AFD
	 * @return state(0), that is always the initial state
	 */
	public DFAState getInitialState()
	{
		for (int i = 0; i < states.length - 1; i++)
		{
			if (states[i].getId() == 0)
			{
				return states[i];
			}
		}
		
		// there is no initial state
		System.out.println("  >> ERROR! Initial State does not exist!");
		return null;		 
	}
	
	/**
	 * Verifies if the state already exists in the automaton
	 * @param state		the state to be verified
	 * @return			TRUE if the state is Available (does not exist). Otherwise, FALSE (state already exists)
	 */
	private boolean verifyState (DFAState state)
	{
		for (int i = 0; i < states.length - 1; i++)
		{
			if (states[i].getId() == state.getId())
			{
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Override ToString
	 */
	public String toString()								
	{ 
		return this.name; 
	}
	
	/**
	 * Override equals
	 */
	public boolean equals(Object obj)
	{
		if (obj == null)	
			return false;
		else if (obj.getClass() != getClass())
			return false;
		else if (obj == this)
            return true;
		
		DFA dfa = (DFA)obj;
		return (dfa.toString() == this.toString());        
	}
	
	public String getName()
	{
		return this.name;
	}
	
	public DFAState[] getStates()
	{
		DFAState[] temp = new DFAState[this.states.length-1];
		System.arraycopy(this.states, 0, temp, 0, this.states.length-1);
		return temp;
	}
	
	public static void main(String[] args) {
	}
}
